package net.cyndeline.componentSystem.movement

import net.cyndeline.entitySystem.AbstractEventHandlerSystem
import net.cyndeline.events.movement.MovementEvent
import net.cyndeline.entitySystem.{ EntityRef, Event }
import net.cyndeline.entitySystem.defaultImpl.Aspect
import net.cyndeline.components.world.{ PositionComponent, OnMapComponent }
import language.postfixOps
import net.cyndeline.components.world.Position
import com.escalatesoft.subcut.inject.BindingModule
import com.escalatesoft.subcut.inject.Injectable
import net.cyndeline.events.movement.Movement
import net.cyndeline.components.world.OnMap
import net.cyndeline.events.gameplay.ActionCompleteEvent
import net.cyndeline.events.gameplay.ActionComplete

/**
 * Moves an agent from one position on the map to another. Performs no
 * fail-checking.
 */
class MovementProcessingSystem(implicit val bindingModule: BindingModule) 
extends AbstractEventHandlerSystem(
    new Aspect().getAll(classOf[Position], classOf[OnMap]), classOf[Movement]) 
	with Injectable {
  
  override def onEvent(event: Event, entity: EntityRef): Unit = {    
    event match {
      case m: Movement => {
        process(m, entity)
      }
      case _ => {}
    }
  }
  
  private def process(move: MovementEvent, entity: EntityRef) {
    val onMap = entity.getComponent(classOf[OnMap]).get
    val map = onMap.map
    val position = entity.getComponent(classOf[Position]).get
    val stopX = move.stop._1
    val stopY = move.stop._2
    val newPosition = injectOptional[PositionComponent] getOrElse { new Position }
    	newPosition.x = stopX
    	newPosition.y = stopY
    map removeObject entity
    entity addComponent newPosition
    map addObject entity
    
    /* Signal that an action has been performed */
    move.makeNoncancellable()
    val actionComplete = injectOptional[ActionCompleteEvent] getOrElse { new ActionComplete() }
    entity.send(actionComplete)
  }
}